<?php
// 应用公共文件
use app\common\service\AuthService;
use think\facade\Cache;
use think\facade\Env;
use app\common\constants\CommonConstant;
use EasyAdmin\upload\Uploadfile;
use think\File;
use think\file\UploadedFile;
use think\facade\Db;
use think\facade\Log;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use app\admin\model\FigureSystem;
use app\admin\model\FigureUser;
use app\common\service\ApiV3Pay;
use app\admin\model\template\ConsumeSuccess;
use FFMpeg\FFMpeg;

function msg($data, $code, $msg = "", $count = null)
{
    return json([
        "code" => $code,
        "message" => $msg,
        "data" => $data,
        "count" => $count
    ]);
}

function result($errno, $message, $data = '')
{
    exit(json_encode(array(
        'errno' => $errno,
        'message' => $message,
        'data' => $data
    )));
}

function fieldexists($tablename, $fieldname)
{
    $isexists = Db::query("DESCRIBE " . $tablename . " `{$fieldname}`", array());
    return !empty($isexists) ? true : false;
}

function tableexists($table)
{
    if (!empty($table)) {
        $data = Db::query("SHOW TABLES LIKE '{$table}'", array());
        $rel_data = array();
        foreach ($data as $k => $v) {
            $data1 = array_values($v);
            $rel_data = array_merge($data1, $rel_data);
        }
        if (!empty($rel_data)) {
            $tablename = $table;
            if (in_array($tablename, $rel_data)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}

function get_http_type()
{
    $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
    return $http_type;
}

function getRandNumber($start, $end, $length)
{
    // 初始化变量为0
    $connt = 0;
    // 建一个新数组
    $temp = array();
    while ($connt < $length) {
        // 在一定范围内随机生成一个数放入数组中
        $temp[] = mt_rand($start, $end);
        // $data = array_unique($temp);
        // 去除数组中的重复值用了“翻翻法”，就是用array_flip()把数组的key和value交换两次。这种做法比用 array_unique() 快得多。
        $data = array_flip(array_flip($temp));
        // 将数组的数量存入变量count中
        $connt = count($data);
    }
    // 为数组赋予新的键名
    shuffle($data);
    // 数组转字符串
    $str = implode(",", $data);
    // 替换掉逗号
    $number = str_replace(',', '', $str);
    return $number;
}

function getDuration($type, $url)
{
    $name = time() . rand(999, 9999);

    $path = root_path() . 'public/uploads/temp';

    if (!is_dir($path)) {
        mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
    }

    $type == 1 ? ($path .= '/voice-' . $name . '.mp3') : ($path .= '/video-' . $name . '.mp4');

    // 使用cURL下载视频
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    $pathData = curl_exec($ch);
    curl_close($ch);
    if ($pathData == false) {
        $pathData = file_get_contents($url);
        file_put_contents($path, $pathData);
        require_once root_path() . "vendor/getID3-master/getid3/getid3.php";
        $getID3 = new \getID3();
        $ThisFileInfo = $getID3->analyze($path);
        if ($ThisFileInfo['mime_type'] == 'audio/wav') {
            if ($ThisFileInfo['playtime_seconds']) {
                $duration = $ThisFileInfo['playtime_seconds'];
            } else {
                $duration = isset($ThisFileInfo['riff']['header_size']) ? ($ThisFileInfo['riff']['header_size'] - 42) / 88200 : 0;
            }

            // $duration = isset($ThisFileInfo['riff']['header_size']) ? ($ThisFileInfo['riff']['header_size'] - 42) / 88200 : 0;
        } else {
            $duration = isset($ThisFileInfo['playtime_seconds']) ? $ThisFileInfo['playtime_seconds'] : 0;
        }
        return $duration;
    } else {
        $pathFile = fopen($path, 'wb');
        fwrite($pathFile, $pathData);
    }
    // 将视频数据保存到本地文件
    require_once root_path() . "vendor/getID3-master/getid3/getid3.php";
    $getID3 = new \getID3();
    $ThisFileInfo = $getID3->analyze($path);
    if ($ThisFileInfo['mime_type'] == 'audio/wav') {
        if ($ThisFileInfo['playtime_seconds']) {
            $duration = $ThisFileInfo['playtime_seconds'];
        } else {
            $duration = isset($ThisFileInfo['riff']['header_size']) ? ($ThisFileInfo['riff']['header_size'] - 42) / 88200 : 0;
        }
        // $duration = isset($ThisFileInfo['riff']['header_size']) ? ($ThisFileInfo['riff']['header_size'] - 42) / 88200 : 0;
    } else {
        $duration = isset($ThisFileInfo['playtime_seconds']) ? $ThisFileInfo['playtime_seconds'] : 0;
    }
    unlink($path);
    fclose($pathFile);
    return $duration;
}

function user_balance_used($uid, $log_no, $type, $way, $total = 1, $desc = '')
{
    $t = time();
    FigureUser::where('maturity_time', '<', $t)->update([
        'is_member' => 0
    ]);

    $user = FigureUser::where('id', $uid)->find();

    $insertLog = array(
        'uid' => $uid,
        'log_no' => $log_no,
        'type' => $type,
        'way' => $way
    );

    $tally = 0;
    $money = 0;

    $consumeData = [
        'openid' => $user['openid']
    ];

    if ($way == 3 || $way == 30) { // 声音克隆
        $insertLog['way'] = 3;
        if ($way == 30 && $user['voice_twin_count'] >= 1) {

            $money = 1;
            $tally = 1;

            $desc = "声音克隆高保真";

            $insertLog['current'] = $user['voice_twin_count'];
            $insertLog['b_type'] = 2;
            FigureUser::where('id', $uid)->save([
                'voice_twin_count' => Db::raw('voice_twin_count-' . $money)
            ]);
            $consumeData['remain'] = $user['voice_twin_count'] - $money;
        } else {

            $money = $way == 3 ? sysconfig('tally', 'voice_deduct') : sysconfig('tally', 'voice_high_deduct');
            $tally = $way == 3 ? sysconfig('tally', 'voice_deduct') : sysconfig('tally', 'voice_high_deduct');

            $desc = $way == 3 ? "声音克隆入门版" : "声音克隆高保真一次";

            $insertLog['current'] = $user['balance'];

            if ($way == 3) {

                if (!$user['is_member']) {
                    FigureUser::where('id', $uid)->save([
                        'balance' => Db::raw('balance-' . $money)
                    ]);
                }
            } elseif ($way == 30) {
                if (!$user['is_member'] || ($user['is_member'] && $user['voice_twin_count'] < 1)) {
                    FigureUser::where('id', $uid)->save([
                        'balance' => Db::raw('balance-' . $money)
                    ]);
                }
            }

            $consumeData['remain'] = round($user['balance'] - $money, 2);
        }
    } elseif ($way == 4 || $way == 40 || $way == 41 || $way == 42 || $way == 43) { // 形象克隆

        $insertLog['way'] = 4;

        if ($way == 40) {
            $money = $tally = sysconfig('tally', 'avatar_high_deduct');
        } elseif ($way == 41) {
            $money = $tally = sysconfig('tally', 'avatar_high_deduct_two');
        } elseif ($way == 42) {
            $money = $tally = sysconfig('tally', 'avatar_deduct');
        } elseif ($way == 43) {
            $money = $tally = sysconfig('tally', 'avatar_deduct_four');
        }
        /* $money = $way == 4 ? sysconfig('tally', 'avatar_deduct') : sysconfig('tally', 'avatar_high_deduct');
         $tally = $way == 4 ? sysconfig('tally', 'avatar_deduct') : sysconfig('tally', 'avatar_high_deduct');*/


        $insertLog['current'] = $user['balance'];

        if (!$user['is_member']) {
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }

        $consumeData['remain'] = round($user['balance'] - $money, 2);
    } elseif ($way == 5) { // 视频换脸 扣点数

        $tally = sysconfig('tally', 'face_deduct');
        $money = round($total * $tally, 2);

        $desc = "视频换脸 ";

        $insertLog['current'] = $user['balance'];

        if (!$user['is_member']) {
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }

        $consumeData['remain'] = round($user['balance'] - $money, 2);
    } elseif ($way == 6) { // 视频剪辑 扣点数

        $total = ceil($total);

        if (($user['is_member'] && $user['second_infinite'] == 1) || ($user['is_member'] && $user['second_infinite'] == 0 && $user['second'] >= $total)) {

            $tally = 1;
            $money = $total;

            //   $desc = "线路一创作";

            $insertLog['current'] = $user['second'];
            $insertLog['b_type'] = 3;

            $consumeData['remain'] = $user['second'] - $money;

            if ($user['second_infinite'] != 1) {
                FigureUser::where('id', $uid)->save([
                    'second' => Db::raw('second-' . $money)
                ]);
            }
        } else {

            $tally = (float)sysconfig('tally', 'video_deduct');

            $money = round((float)$total * $tally, 2);

            // $desc = "线路一创作" . $total . "秒";

            $insertLog['current'] = $user['balance'];

            $consumeData['remain'] = round($user['balance'] - $money, 2);

            if (!$user['is_member'] || ($user['is_member'] && $user['second'] < $total)) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }
    } elseif ($way == 8) { // AI文案 扣点数


        if ($user['is_member'] && $user['ai_copywriting_times'] >= 1) {
            $insertLog['current'] = $user['ai_copywriting_times'];
            $desc = "AI文案";
            $consumeData['remain'] = round($user['ai_copywriting_times'] - 1, 2);
            FigureUser::where('id', $uid)->save([
                'ai_copywriting_times' => Db::raw('ai_copywriting_times-' . 1)
            ]);
        } else {
            $tally = sysconfig('tally', 'ai_create_deduct');
            $desc = "AI文案";
            $insertLog['current'] = $user['balance'];
            $money = round((float)$total * $tally, 2);
            $consumeData['remain'] = round($user['balance'] - $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);

        }

    } elseif ($way == 9 || $way == 90) { // 照片克隆 扣点数

        $money = $way == 9 ? sysconfig('tally', 'photo_deduct') : sysconfig('tally', 'photo_high_deduct');
        $tally = $way == 9 ? sysconfig('tally', 'photo_deduct') : sysconfig('tally', 'photo_high_deduct');

        $desc = $way == 9 ? "入门照片克隆" : "高级照片克隆";

        $insertLog['way'] = 9;
        $insertLog['current'] = $user['balance'];

        if (!$user['is_member']) {
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }

        $consumeData['remain'] = round($user['balance'] - $money, 2);
    } elseif ($way == 10) { // 入门视频剪辑 扣点数

        $total = (float)$total;

        if (($user['is_member'] && $user['second_infinite'] == 1) || ($user['is_member'] && $user['second_infinite'] == 0 && $user['second'] >= $total * 60)) {

            $tally = 1;
            $money = $total * 60;

            //  $desc = "线路三视频创作";

            $insertLog['current'] = $user['second'];
            $insertLog['b_type'] = 3;

            $consumeData['remain'] = $user['second'] - $money;

            if ($user['second_infinite'] != 1) {
                FigureUser::where('id', $uid)->save([
                    'second' => Db::raw('second-' . $money)
                ]);
            }
        } else {

            $tally = (float)sysconfig('tally', 'composite_deduct');

            $money = bcmul($total, $tally, 2);

            // $desc = "线路三视频创作" . $total . "分钟";

            $insertLog['current'] = $user['balance'];

            $consumeData['remain'] = round($user['balance'] - $money, 2);


            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);

        }
    } elseif ($way == 11) {
        $tally = sysconfig('tally', 'clip_price');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "二次剪辑";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        } else {
            if ($tally <= 0) {
                return;
            }
            $money = bcmul($total, $tally, 2);
            $desc = "二次剪辑失败退款";
            $consumeData['remain'] = bcmul($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance+' . $money)
            ]);
        }
    } elseif ($way == 12) {

        if ($user['is_member'] && $user['ai_copywriting_times'] >= 1) {
            $insertLog['current'] = $user['ai_copywriting_times'];
            $desc = "AI视频提取文案";
            $consumeData['remain'] = round($user['ai_copywriting_times'] - 1, 2);
            FigureUser::where('id', $uid)->save([
                'ai_copywriting_times' => Db::raw('ai_copywriting_times-' . 1)
            ]);
        } else {
            $tally = sysconfig('tally', 'ai_video_extraction');
            $desc = "AI视频提取文案";
            $insertLog['current'] = $user['balance'];
            $money = round((float)$total * $tally, 2);
            $consumeData['remain'] = round($user['balance'] - $money, 2);
            if (!$user['is_member']) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }

    } elseif ($way == 13) {
        //  按分钟计算
        $money = $total;
        if (($user['is_member'] && $user['second_infinite'] == 1) || ($user['is_member'] && $user['second_infinite'] == 0 && $user['second'] >= $money)) {

            //  $desc = "线路二视频创作";

            $insertLog['current'] = $user['second'];
            $insertLog['b_type'] = 3;

            $consumeData['remain'] = $user['second'] - $money;

            if ($user['second_infinite'] != 1) {
                FigureUser::where('id', $uid)->save([
                    'second' => Db::raw('second-' . $money)
                ]);
            }
        } else {

            $tally = (float)sysconfig('tally', 'woni_video_deduct');

            $money = round((float)$total * $tally, 2);

            //  $desc = "线路二视频创作" . $total . "秒";

            $insertLog['current'] = $user['balance'];

            $consumeData['remain'] = round($user['balance'] - $money, 2);

            if (!$user['is_member'] || ($user['is_member'] && $user['second'] < $money)) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }
    } elseif ($way == 14) {
        //  按分钟计算
        if (($user['is_member'] && $user['high_fidelity_words_number'] >= $total * 100)) {
            $tally = $money = $total * 100;
            $desc = "高保证声音合成" . $money . "字";
            $insertLog['current'] = $user['high_fidelity_words_number'];
            $insertLog['b_type'] = 4;
            $consumeData['remain'] = $user['high_fidelity_words_number'] - $money;
            FigureUser::where('id', $uid)->save([
                'high_fidelity_words_number' => Db::raw('high_fidelity_words_number-' . $money)
            ]);

        } else {
            $tally = (float)sysconfig('tally', 'high_fidelity_sound');
            $tally = $money = round((float)$total * $tally, 2);
            $desc = "高保证声音合成" . $total * 100 . "字";
            $insertLog['current'] = $user['balance'];
            $consumeData['remain'] = round($user['balance'] - $money, 2);
            if (!$user['is_member'] || ($user['is_member'] && $user['second'] < $money)) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }
    } elseif ($way == 15) {

        if (($user['is_member'] && $user['xunfei_sound_clone_words_number'] > 0)) {
            $money = $tally = 1;
            $desc = "专业版声音克隆";
            $insertLog['b_type'] = 2;
            $insertLog['current'] = $user['xunfei_sound_clone_words_number'];
            FigureUser::where('id', $uid)->save([
                'xunfei_sound_clone_words_number' => Db::raw('xunfei_sound_clone_words_number-' . $money)
            ]);
            $consumeData['remain'] = round($user['xunfei_sound_clone_words_number'] - $money, 2);
        } else {
            $money = $tally = sysconfig('tally', 'xunfei_sound_train');
            $desc = "专业版声音克隆";
            $insertLog['current'] = $user['balance'];
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);

            $consumeData['remain'] = round($user['balance'] - $money, 2);
        }

    } elseif ($way == 16) {
        if (($user['is_member'] && $user['xunfei_sound_generate_words_number'] >= $total * 100)) {
            $tally = $money = $total * 100;
            $desc = "声音专业版合成" . $money . "字";
            $insertLog['current'] = $user['xunfei_sound_generate_words_number'];
            $insertLog['b_type'] = 4;
            $consumeData['remain'] = $user['xunfei_sound_generate_words_number'] - $money;
            FigureUser::where('id', $uid)->save([
                'xunfei_sound_generate_words_number' => Db::raw('xunfei_sound_generate_words_number-' . $money)
            ]);

        } else {
            $tally = (float)sysconfig('tally', 'xunfei_sound_generate');

            $tally = $money = round((float)$total * $tally, 2);

            $desc = "声音专业版合成" . $total * 100 . "字";
            $insertLog['current'] = $user['balance'];
            $consumeData['remain'] = round($user['balance'] - $money, 2);
            if (!$user['is_member'] || ($user['is_member'] && $user['second'] < $money)) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }
    } elseif ($way == 17) {

        if ($user['is_member'] && $user['ai_title_times'] >= $total) {
            $insertLog['current'] = $user['ai_title_times'];
            $desc = "AI标题生成";
            $consumeData['remain'] = round($user['ai_title_times'] - $total, 2);
            FigureUser::where('id', $uid)->save([
                'ai_title_times' => Db::raw('ai_title_times-' . $total)
            ]);
        } else {
            $tally = sysconfig('tally', 'ai_title_create_deduct');
            $desc = "AI标题生成";
            $insertLog['current'] = $user['balance'];
            $money = round((float)$total * $tally, 2);
            $consumeData['remain'] = round($user['balance'] - $money, 2);
            if (!$user['is_member']) {
                FigureUser::where('id', $uid)->save([
                    'balance' => Db::raw('balance-' . $money)
                ]);
            }
        }

    } elseif ($way == 18) {
        $tally = sysconfig('tally', 'douyin_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "发布抖音视频";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        } else {
            if ($tally <= 0) {
                return;
            }
            $money = bcmul($total, $tally, 2);
            $desc = "抖音视频失败";
            $consumeData['remain'] = bcmul($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance+' . $money)
            ]);
        }
    } elseif ($way == 19) {
        $tally = sysconfig('tally', 'kuaishou_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "发布快手视频";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        } else {
            if ($tally <= 0) {
                return;
            }
            $money = bcmul($total, $tally, 2);
            $desc = "发布快手视频失败";
            $consumeData['remain'] = bcmul($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance+' . $money)
            ]);
        }
    } elseif ($way == 20) {
        $tally = sysconfig('tally', 'shipinghao_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "发布视频号视频";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        } else {
            if ($tally <= 0) {
                return;
            }
            $money = bcmul($total, $tally, 2);
            $desc = "发布视频号失败";
            $consumeData['remain'] = bcmul($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance+' . $money)
            ]);
        }
    } elseif ($way == 21) {
        $tally = sysconfig('tally', 'xiaohongshu_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "发布小红薯视频";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        } else {
            if ($tally <= 0) {
                return;
            }
            $money = bcmul($total, $tally, 2);
            $desc = "发布小红薯失败";
            $consumeData['remain'] = bcmul($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance+' . $money)
            ]);
        }
    } elseif ($way == 22) {
        $tally = sysconfig('tally', 'douyin_scan_code');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取抖音二维码";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 23) {
        $tally = sysconfig('tally', 'douyin_authorize');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "抖音授权";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 24) {
        $tally = sysconfig('tally', 'xiaohongshu_scan_code');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取视频号二维码";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 25) {
        $tally = sysconfig('tally', 'shipinghao_authorize');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取视频号授权";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 26) {
        $tally = sysconfig('tally', 'xiaohongshu_scan_code');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取小红薯二维码";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 27) {
        $tally = sysconfig('tally', 'xiaohongshu_authorize');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取小红薯授权";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 28) {
        //  按分钟计算
        $money = $total * 60;
        if (($user['is_member'] && $user['second_infinite'] == 1) || ($user['is_member'] && $user['second_infinite'] == 0 && $user['second'] >= $money)) {

            //$desc = "线路二视频创作";

            $insertLog['current'] = $user['second'];
            $insertLog['b_type'] = 3;

            $consumeData['remain'] = $user['second'] - $money;

            if ($user['second_infinite'] != 1) {
                FigureUser::where('id', $uid)->save([
                    'second' => Db::raw('second-' . $money)
                ]);
            }
        } else {

            $tally = (float)sysconfig('tally', 'composite_deduct_four');

            $money = round((float)$total * $tally, 2);

            // $desc = "线路二视频创作" . $total . "分钟";

            $insertLog['current'] = $user['balance'];

            $consumeData['remain'] = round($user['balance'] - $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);

        }
    } elseif ($way == 29) {
        $tally = sysconfig('tally', 'xiaohongshu_authorize');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "获取小红薯授权";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 32) {
        $tally = sysconfig('tally', 'douyin_homepage');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "IP账号采集";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    } elseif ($way == 31) {
        $tally = sysconfig('tally', 'douyin_homepage_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "解析作品文案";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 33) {
        $tally = sysconfig('tally', 'img_replacement');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "ai换装";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 34) {
        $tally = sysconfig('tally', 'old_image_repair');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "老照片修复";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 35) {
        $tally = sysconfig('tally', 'face_transplant');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "图像融和";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 36) {
        $tally = sysconfig('tally', 'change_hair');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "换发";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 37) {
        $tally = sysconfig('tally', 'high_definition_img');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "高清照片";

            $insertLog['current'] = $user['balance'];

            $money = bcmul($total, $tally, 2);

            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 38) {
        $tally = sysconfig('tally', 'separate_audio');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "音频提取";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 39) {
        $tally = sysconfig('tally', 'img_generate_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "图生模特";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 50) {
        $tally = sysconfig('tally', 'wensheng_picture');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "文生图";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 51) {
        $tally = sysconfig('tally', 'wensheng_picture');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "文生模特";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 52) {
        $tally = sysconfig('tally', 'img_generate_video');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "图生视频";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 53) {
        $money = $tally = $total;
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "智能体扣点";
            $insertLog['current'] = $user['balance'];
//          $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }elseif ($way == 54) {
        $tally = sysconfig('tally', 'handheld_product');
        if ($type == 2) {
            if ($tally <= 0) {
                return;
            }
            $desc = "手持商品";
            $insertLog['current'] = $user['balance'];
            $money = bcmul($total, $tally, 2);
            $consumeData['remain'] = bcsub($user['balance'], $money, 2);
            FigureUser::where('id', $uid)->save([
                'balance' => Db::raw('balance-' . $money)
            ]);
        }
    }



    $consumeData['name'] = $desc;
    $consumeData['money'] = $money;
    $consumeData['time'] = date('Y-m-d H:i', time());
    $consumeSuccess = new ConsumeSuccess($consumeData);
    $consumeSuccess->send();
    $insertLog['money'] = $money;
    $insertLog['desc'] = $desc;
    $insertLog['tally'] = $tally;

    $log = new \app\admin\model\FigureBalanceLog();
    $log->save($insertLog);
}

function order_refund($log_no, $total, $refund)
{
    $payconfig = sysconfig('pay');

    if (empty($payconfig)) {
        return json_encode([
            'code' => 0,
            'msg' => "请检查后台支付配置"
        ]);
        exit();
    }

    $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    $pay_type = $payconfig['pay_type'];

    if ($pay_type == 2) { // 子商户支付
        $send_data = array(
            'appid' => $payconfig['pay_service_appid'],
            'mch_id' => $payconfig['pay_service_mchid'],
            'sub_appid' => $payconfig['pay_appid'],
            'sub_mch_id' => $payconfig['pay_mchid'],
            'nonce_str' => getNonceStr(32),
            'out_trade_no' => $log_no,
            'out_refund_no' => getPayNo('RE') . rand(999, 9999),
            'total_fee' => $total * 100,
            'refund_fee' => $refund * 100
        );
    } else {
        $send_data = array(
            'appid' => $payconfig['pay_appid'],
            'mch_id' => $payconfig['pay_mchid'],
            'nonce_str' => getNonceStr(32),
            'out_trade_no' => $log_no,
            'out_refund_no' => getPayNo('RE') . rand(999, 9999),
            'total_fee' => $total * 100,
            'refund_fee' => $refund * 100
        );
    }

    $sign = MakeSign($send_data, $payconfig['pay_api_key']);

    $send_data['sign'] = $sign;

    $result = FromXml(refund_request($url, ToXml($send_data), array(
        'cert' => root_path() . "/public/cert/apiclient_cert.pem",
        'key' => root_path() . "/public/cert/apiclient_key.pem"
    )));

    if (empty($result)) {
        return json_encode([
            'code' => 0,
            'msg' => "请检查后台支付配置"
        ]);
        exit();
    }

    if (!empty($result['return_code']) && $result['return_code'] != 'SUCCESS') {
        return json_encode([
            'code' => 0,
            'msg' => $result['return_msg'],
            'data' => $send_data
        ]);
        exit();
    }

    if (!empty($result['result_code']) && $result['result_code'] != 'SUCCESS') {
        return json_encode([
            'code' => 0,
            'msg' => $result['err_code_des'],
            'data' => $send_data
        ]);
        exit();
    }

    if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {

        $insertLog = array(
            'price' => $refund,
            'out_trade_no' => $send_data['out_trade_no'],
            'out_refund_no' => $send_data['out_refund_no'],
            'total_fee' => $send_data['total_fee'],
            'refund_fee' => $send_data['refund_fee'],
            'result' => json_encode($result)
        );

        $log = new \app\admin\model\FigureRefundLog();
        $log->save($insertLog);

        return json_encode([
            'code' => 1,
            'msg' => "退款成功"
        ]);
        exit();
    } else {

        $msg = empty($result['err_code_des']) ? $result['return_msg'] : $result['err_code_des'];

        return json_encode([
            'code' => 0,
            'msg' => "微信商户" . $msg,
            'data' => $send_data
        ]);
        exit();
    }
}

function sendMoney($log_no, $money, $openid)
{
    $payconfig = sysconfig('pay');

    if (empty($payconfig)) {
        return json_encode([
            'code' => 0,
            'msg' => "请检查后台支付配置"
        ]);
        exit();
    }

    $total_amount = (100) * $money;

    $pay_remit_type = $payconfig['pay_remit_type'];

    if (empty($pay_remit_type) || $pay_remit_type == 1) {  // 企业转账到零钱
        $data = array(
            'mch_appid' => $payconfig['pay_appid'], // 商户账号appid
            'mchid' => $payconfig['pay_mchid'], // 商户号
            'nonce_str' => createNoncestr(), // 随机字符串
            'partner_trade_no' => date('YmdHis') . rand(1000, 9999), // 商户订单号
            'openid' => $openid, // 用户openid
            'check_name' => 'NO_CHECK', // 校验用户姓名选项,
            'amount' => $total_amount, // 金额
            'desc' => "提现", // 企业付款描述信息
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR']
        );
        $data = array_filter($data);
        ksort($data);
        $str = '';
        foreach ($data as $k => $v) {
            $str .= $k . '=' . $v . '&';
        }
        $str .= 'key=' . $payconfig['pay_api_key'];
        $data['sign'] = md5($str);
        $xml = ToXml($data);
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; // 调用接口
        $res = refund_request($url, $xml, array(
            'cert' => root_path() . "/public/cert/apiclient_cert.pem",
            'key' => root_path() . "/public/cert/apiclient_key.pem"
        ));
        $result = FromXml($res);
        Log::error("common sendMoney:" . json_encode($result));

        if (empty($result)) {
            return json_encode([
                'code' => 0,
                'msg' => "请检查后台支付配置"
            ]);
            exit();
        }
        if (!empty($result['result_code']) && $result['result_code'] != 'SUCCESS') {
            return json_encode([
                'code' => 0,
                'msg' => "微信商户" . $result['err_code_des']
            ]);
            exit();
        }

        return json_encode([
            'code' => 1,
            'msg' => "打款成功"
        ]);
        exit();
    } else {
        if ($payconfig['pay_type'] == 2) { // 服务商
            $payKey = root_path() . "/public/cert/apiclient_key.pem";
            $getData = new ApiV3Pay($payconfig['pay_appid'], $payconfig['pay_mchid'], $payKey, $payconfig['pay_serial_no'], $payconfig['pay_service_appid']);
            $requestBody = $getData->partnerTransfer($log_no, $total_amount, $openid); // 获取请求主体的json数据
            if (!empty($requestBody['code'])) {
                echo json_encode([
                    'code' => '0',
                    'msg' => "微信商户" . $requestBody['message']
                ]);
                exit();
            }
            return json_encode([
                'code' => 1,
                'msg' => "打款成功"
            ]);
        } else {
            if ($payconfig['wx_transfer_version'] == 1) {
                $payKey = root_path() . "/public/cert/apiclient_key.pem";
                $getData = new ApiV3Pay($payconfig['pay_appid'], $payconfig['pay_mchid'], $payKey, $payconfig['pay_serial_no']);
                $requestBody = $getData->transfer($log_no, $total_amount, $openid); // 获取请求主体的json数据
                if (!empty($requestBody['code'])) {
                    echo json_encode([
                        'code' => '0',
                        'msg' => "微信商户" . $requestBody['message']
                    ]);
                    exit();
                }
                return json_encode([
                    'code' => 1,
                    'msg' => "打款成功"
                ]);
                exit();
            } else {
                $payKey = root_path() . "/public/cert/apiclient_key.pem";
                $getData = new ApiV3Pay($payconfig['pay_appid'], $payconfig['pay_mchid'], $payKey, $payconfig['pay_serial_no']);
                $transfer_scene_id = $payconfig['transfer_scene_id'];
                if (empty($transfer_scene_id)) {
                    return json_encode([
                        'code' => '0',
                        'msg' => "请绑定场景id"
                    ]);
                    exit();
                }
                $requestBody = $getData->transferNew($log_no, $total_amount, $openid, $transfer_scene_id, $payconfig['pay_platform_serial_no']); // 获取请求主体的json数据

                if (isset($requestBody['code'])) {
                    return json_encode([
                        'code' => '0',
                        'msg' => "微信商户" . $requestBody['message']
                    ]);
                    exit();
                }
                return json_encode([
                    'code' => 1,
                    'msg' => "打款成功",
                    'data' => $requestBody
                ]);
                exit();
            }
        }


    }
}

function getRandomLower()
{
    $chars = "abcdefghijklmnopqrstuvwxyz";
    $str = substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    return $str;
}

function getNonceStr($length = 32)
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
}

function MakeSign($array, $key)
{
    // 签名步骤一：按字典序排序参数
    ksort($array);
    $string = ToUrlParams($array);
    // 签名步骤二：在string后加入KEY
    $string = $string . "&key=" . $key;
    // 签名步骤三：MD5加密
    $string = md5($string);
    // 签名步骤四：所有字符转为大写
    $result = strtoupper($string);
    return $result;
}

function ToUrlParams($arr)
{
    $buff = "";
    foreach ($arr as $k => $v) {
        if ($k != "sign" && $v != "" && !is_array($v)) {
            $buff .= $k . "=" . $v . "&";
        }
    }
    $buff = trim($buff, "&");
    return $buff;
}

function FromXml($xml)
{
    // 将XML转为array
    // 禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $arr;
}

function ToXml($array)
{
    $xml = "<xml>";
    foreach ($array as $key => $val) {
        if ($key != 'body') {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
        } else {
            $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
    }
    $xml .= "</xml>";
    return $xml;
}

function sign_pay($arr, $appid, $pay_key)
{
    $package = "prepay_id=" . $arr['prepay_id'];
    $signType = "MD5";
    $time = (int)time();
    $array = array(
        'appId' => $appid,
        'nonceStr' => $arr['nonce_str'],
        'package' => $package,
        'signType' => $signType,
        'timeStamp' => (string)$time
    );
    $sign_str = MakeSign($array, $pay_key);

    $array['paySign'] = $sign_str;
    return $array;
}

if (!function_exists('__url')) {

    /**
     * 构建URL地址
     *
     * @param string $url
     * @param array $vars
     * @param bool $suffix
     * @param bool $domain
     * @return string
     */
    function __url(string $url = '', array $vars = [], $suffix = true, $domain = false)
    {
        return url($url, $vars, $suffix, $domain)->build();
    }
}

if (!function_exists('password')) {

    /**
     * 密码加密算法
     *
     * @param $value 需要加密的值
     * @param $type 加密类型，默认为md5
     *            （md5, hash）
     * @return mixed
     */
    function password($value)
    {
        $value = sha1('blog_') . md5($value) . md5('_encrypt') . sha1($value);
        return sha1($value);
    }
}

if (!function_exists('xdebug')) {

    /**
     * debug调试
     *
     * @deprecated 不建议使用，建议直接使用框架自带的log组件
     * @param string|array $data
     *            打印信息
     * @param string $type
     *            类型
     * @param string $suffix
     *            文件后缀名
     * @param bool $force
     * @param null $file
     */
    function xdebug($data, $type = 'xdebug', $suffix = null, $force = false, $file = null)
    {
        !is_dir(runtime_path() . 'xdebug/') && mkdir(runtime_path() . 'xdebug/');
        if (is_null($file)) {
            $file = is_null($suffix) ? runtime_path() . 'xdebug/' . date('Ymd') . '.txt' : runtime_path() . 'xdebug/' . date('Ymd') . "_{$suffix}" . '.txt';
        }

        file_put_contents($file, "[" . date('Y-m-d H:i:s') . "] " . "========================= {$type} ===========================" . PHP_EOL, FILE_APPEND);

        $str = is_string($data) ? $data : ((is_array($data) || is_object($data)) ? print_r($data, true) : var_export($data, true));
        $str = $str . PHP_EOL;
        $force ? file_put_contents($file, $str) : file_put_contents($file, $str, FILE_APPEND);
    }
}

if (!function_exists('sysconfig')) {

    /**
     * 获取系统配置信息
     *
     * @param
     *            $group
     * @param null $name
     * @return array|mixed
     */
    function sysconfig($group, $name = null)
    {
        $where = [
            'group' => $group
        ];
        $value = empty($name) ? Cache::get("sysconfig_{$group}") : Cache::get("sysconfig_{$group}_{$name}");
        if (empty($value)) {
            if (!empty($name)) {
                $where['name'] = $name;
                $value = \app\admin\model\SystemConfig::where($where)->value('value');
                Cache::tag('sysconfig')->set("sysconfig_{$group}_{$name}", $value, 3600);
            } else {
                $value = \app\admin\model\SystemConfig::where($where)->column('value', 'name');
                Cache::tag('sysconfig')->set("sysconfig_{$group}", $value, 3600);
            }
        }
        return $value;
    }
}

if (!function_exists('agencyconfig')) {

    /**
     * 获取系统配置信息
     *
     * @param
     *            $group
     * @param null $name
     * @return array|mixed
     */
    function agencyconfig($agency_id, $name = null)
    {
        $where = [
            'agency_id' => $agency_id
        ];

        if (!empty($name)) {
            $value = \app\admin\model\MovieConfig::where($where)->value($name);
        } else {
            $value = \app\admin\model\MovieConfig::where($where)->find();
        }
        return $value;
    }
}

if (!function_exists('array_format_key')) {

    /**
     * 二位数组重新组合数据
     *
     * @param
     *            $array
     * @param
     *            $key
     * @return array
     */
    function array_format_key($array, $key)
    {
        $newArray = [];
        foreach ($array as $vo) {
            $newArray[$vo[$key]] = $vo;
        }
        return $newArray;
    }
}

if (!function_exists('wtw_request')) {

    /**
     * 请求接口
     *
     * @param unknown $url
     * @param string $data
     * @return mixed
     */
    function wtw_request($url, $data = null)
    {
        $userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 300); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        $info = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            print_r($info);
            print_r(curl_getinfo($curl));
            // echo 'Errno:'.curl_getinfo($curl);//捕抓异常
            // dump(curl_getinfo($curl));
        }
        return $info;
    }
}

if (!function_exists('auth')) {

    /**
     * auth权限验证
     *
     * @param
     *            $node
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function auth($node = null)
    {
        $authService = new AuthService(session('admin.id'));
        $check = $authService->checkNode($node);
        return $check;
    }
}

/**
 * 生成二维码
 */
function common_qr_code($url, $folder)
{
    $upload = sysconfig('upload');

    require_once(root_path() . "vendor/phpqrcode/qrlib.php");
    $errorCorrectionLevel = "L";
    $matrixPointSize = "6.3";
    $margin = "1";
    $name = time() . rand(999, 9999);

    $path = root_path() . 'public/uploads/qr_code/' . $folder;

    if (!is_dir($path)) {
        mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
    }

    $path .= '/code-' . $name . '.png';

    $paths = request()->domain() . '/uploads/qr_code/' . $folder . '/code-' . $name . '.png';
    \QRcode::png($url, $path, $errorCorrectionLevel, $matrixPointSize, $margin);

    $file = new UploadedFile($path, $name . '.png');

    $extension = "png";

    if (empty($upload['upload_type']) || $upload['upload_type'] == 'local') {
        $saveName = \think\facade\Filesystem::disk('public')->putFile('upload', $file);
        $domain = request()->domain();
        $img = $domain . "/" . $saveName;
        return $img;
    } elseif ($upload['upload_type'] == 'alioss') {

        $accesskey = $upload['alioss_access_key_id'];
        $secretkey = $upload['alioss_access_key_secret'];
        $bucket = $upload['alioss_bucket'];
        $domain = $upload['alioss_domain'];

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";

        $ossClient = new \OSS\OssClient($accesskey, $secretkey, 'oss-accelerate.aliyuncs.com');
        $ossClient->uploadFile($bucket, $key, $path);

        $str = "https://" . $domain . "/" . $key;
        unlink($path);
        return $str;
    } elseif ($upload['upload_type'] == 'qnoss') {

        $accesskey = $upload['qnoss_access_key'];
        $secretkey = $upload['qnoss_secret_key'];
        $bucket = $upload['qnoss_bucket'];
        $domain = $upload['qnoss_domain'];

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";

        $auth = new \Qiniu\Auth($accesskey, $secretkey);
        // 生成上传 Token
        $token = $auth->uploadToken($bucket);
        // 初始化 UploadManager 对象并进行文件的上传
        $uploadMgr = new \Qiniu\Storage\UploadManager();
        // 调用 UploadManager 的 putFile 方法进行文件的上传
        list ($ret, $err) = $uploadMgr->putFile($token, $key, $path);
        if ($err !== null) {
            return result(-1, '上传失败');
        } else {
            $str = $domain . "/" . $ret['key'];
            unlink($path);
            return $str;
        }
    } elseif ($upload['upload_type'] == 'txcos') {

        $accesskey = $upload['txcos_secret_id'];
        $secretkey = $upload['txcos_secret_key'];
        $bucket = $upload['txcos_bucket'];
        $domain = $upload['txcos_region'];

        $file = fopen($path, "rb");

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";

        $cosClient = new \Qcloud\Cos\Client([
            'region' => $domain,
            'schema' => "https",
            'credentials' => [
                'secretId' => $accesskey,
                'secretKey' => $secretkey
            ]
        ]);

        $result = $cosClient->putObject([
            'Bucket' => $bucket,
            'Key' => $key,
            'Body' => $file
        ]);

        $str = "https://" . $bucket . ".cos." . $domain . ".myqcloud.com/" . $key;

        unlink($path);
        return $str;
    }
}

/**
 * 生成二维码
 */
function qr_code($id, $toUrl, $folder)
{
    $system = FigureSystem::where('id', 1)->find();

    $appid = $system['appid'];
    $secret = $system['appsecret'];

    if (empty($appid) || empty($secret)) {
        return "";
        exit();
    }

    $url_access_token = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret;
    $json_access_token = sendCmd($url_access_token, array());
    $arr_access_token = json_decode($json_access_token, true);
    $access_token = $arr_access_token['access_token'];
    $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $access_token;
    $qrcode = array(
        'scene' => $id,
        'width' => 320,
        'page' => $toUrl
    );
    $result = sendCmd($url, json_encode($qrcode));

    $err_result = json_decode($result);

    if (isset($err_result->errcode)) {
        return $err_result->errmsg;
        exit();
    }

    $name = time() . rand(999, 9999);

    $path = root_path() . 'public/uploads/qr_code/' . $folder;

    if (!is_dir($path)) {
        mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
    }

    $path .= '/code-' . $name . '.png';

    $paths = request()->domain() . '/uploads/qr_code/' . $folder . '/code-' . $name . '.png';

    file_put_contents($path, $result);

    $file = new UploadedFile($path, $name . '.png');

    $upload = sysconfig('upload');

    $extension = "png";

    if (empty($upload['upload_type']) || $upload['upload_type'] == 'local') {
        $saveName = \think\facade\Filesystem::disk('public')->putFile('upload', $file);
        $domain = request()->domain();
        $img = $domain . "/" . $saveName;
        return $img;
    } elseif ($upload['upload_type'] == 'alioss') {

        $accesskey = $upload['alioss_access_key_id'];
        $secretkey = $upload['alioss_access_key_secret'];
        $bucket = $upload['alioss_bucket'];
        $domain = $upload['alioss_domain'];

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";

        $ossClient = new \OSS\OssClient($accesskey, $secretkey, 'oss-accelerate.aliyuncs.com');
        $ossClient->uploadFile($bucket, $key, $path);

        $str = "https://" . $domain . "/" . $key;
        unlink($path);
        return $str;
    } elseif ($upload['upload_type'] == 'qnoss') {

        $accesskey = $upload['qnoss_access_key'];
        $secretkey = $upload['qnoss_secret_key'];
        $bucket = $upload['qnoss_bucket'];
        $domain = $upload['qnoss_domain'];

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";
        $auth = new \Qiniu\Auth($accesskey, $secretkey);
        // 生成上传 Token
        $token = $auth->uploadToken($bucket);
        // 初始化 UploadManager 对象并进行文件的上传
        $uploadMgr = new \Qiniu\Storage\UploadManager();
        // 调用 UploadManager 的 putFile 方法进行文件的上传
        list ($ret, $err) = $uploadMgr->putFile($token, $key, $path);
        if ($err !== null) {
            return result(-1, '上传失败');
        } else {
            $str = $domain . "/" . $ret['key'];
            unlink($path);
            return $str;
        }
    } elseif ($upload['upload_type'] == 'txcos') {

        $accesskey = $upload['txcos_secret_id'];
        $secretkey = $upload['txcos_secret_key'];
        $bucket = $upload['txcos_bucket'];
        $domain = $upload['txcos_region'];

        // 上传后保存的文件名
        $key = time() . mt_rand(999, 9999) . ".$extension";

        $cosClient = new \Qcloud\Cos\Client([
            'region' => $domain,
            'schema' => "https",
            'credentials' => [
                'secretId' => $accesskey,
                'secretKey' => $secretkey
            ]
        ]);

        $result = $cosClient->putObject([
            'Bucket' => $bucket,
            'Key' => $key,
            'Body' => $result
        ]);

        $str = "https://" . $bucket . ".cos." . $domain . ".myqcloud.com/" . $key;
        unlink($path);
        return $str;
    }
}

function refund_request($url, $data = null, $useCert = null)
{
    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
    if ($data != null) {
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
    }
    curl_setopt($curl, CURLOPT_TIMEOUT, 300); // 设置超时限制防止死循环
    curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    if ($useCert) {
        $cert = $useCert['cert'];
        $key = $useCert['key'];

        curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($curl, CURLOPT_SSLCERT, $cert);
        curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($curl, CURLOPT_SSLKEY, $key);
    }

    $info = curl_exec($curl); // 执行操作
    if (curl_errno($curl)) {
        $error = curl_errno($curl);
        Log::error("curl出错，错误码:$error" . "<br>");

        curl_close($curl);
        return false;
    }
    return $info;
}

function createNonceStr($length = 16)
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
}

function getAccessToken()
{
    $system = FigureSystem::where('id', 1)->find();

    $access_token = "";

    if ($system) {
        $appid = $system['appid'];
        $appsecret = $system['appsecret'];

        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appsecret;

        $res = json_decode(wtw_request($url), true);

        if (!empty($res) && !empty($res['access_token'])) {
            $access_token = $res['access_token'];
        }
    }

    return $access_token;
}

function headerGet($url, $header)
{
    $headers = array(
        'Content-Type: application/json; charset=utf-8'
    );
    if (!empty($header)) {
        $headers = array_merge($headers, $header);
    }

    // 初始化
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    // 执行后不直接打印出来
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    // 跳过证书检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    // 不从证书中检查SSL加密算法是否存在
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    // 执行并获取HTML文档内容
    $output = curl_exec($ch);

    // 释放curl句柄
    curl_close($ch);

    return $output;
}

function httpGet($url)
{
    // 初始化
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    // 执行后不直接打印出来
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    // 跳过证书检查
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    // 不从证书中检查SSL加密算法是否存在
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    // 执行并获取HTML文档内容
    $output = curl_exec($ch);

    // 释放curl句柄
    curl_close($ch);

    return $output;
}

function httpPost($url, $data)
{ // 模拟提交数据函数
    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
    curl_setopt($curl, CURLOPT_POST, true); // 发送一个常规的Post请求
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); // Post提交的数据包
    curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
    curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charset=utf-8'
    )); // 类型为json
    $result = curl_exec($curl); // 执行操作
    if (curl_errno($curl)) {
        echo 'Error POST' . curl_error($curl);
    }
    curl_close($curl); // 关键CURL会话
    return $result; // 返回数据
}

function sendCmd($url, $data)
{
    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'Expect:'
    )); // 解决数据包大不能提交
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
    curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
    curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
    curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循
    curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回

    $tmpInfo = curl_exec($curl); // 执行操作
    if (curl_errno($curl)) {
        echo 'Errno' . curl_error($curl);
    }
    curl_close($curl); // 关键CURL会话
    return $tmpInfo; // 返回数据
}

function http_binary($file, $url)
{
    $stream_opts = [
        "ssl" => [
            "verify_peer" => false,
            "verify_peer_name" => false
        ]
    ];

    $file = file_get_contents($file, false, stream_context_create($stream_opts));

    $request_headers[] = 'Content-Type: video/mp4';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $file);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $reply = curl_exec($ch);
    return $reply;
}

function share_wtw_request($url, $data = null, $headers)
{
    $curl = curl_init(); // 启动一个CURL会话
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); // 请求头参数
    if ($data != null) {
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
    }
    curl_setopt($curl, CURLOPT_TIMEOUT, 300); // 设置超时限制防止死循环
    // curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回

    $info = curl_exec($curl); // 执行操作
    return $info;
}

function getPayNo($text)
{
    return $text . date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}

/**
 * 获取签名token
 */
function signToken($array)
{

    $key = config('app.token_key');

    $key_id = "key_id";

    $token = array(
        'iat' => time(), // 签发时间
        'nbf' => time(), // 开始生效时间
        'exp' => time() + 60 * 60 * 24, // token过期时间
        'data' => [
            'uid' => $array['uid'],
            'tenant_id' => $array['tenant_id']
        ]
    ); // 存储的用户信息

    $jwt = JWT::encode($token, $key, "HS256", $key);
    return $jwt;
}

function format_datetime($date_time, $type = 1, $format = '')
{
    if ($type == 1) {
        $timestamp = strtotime($date_time);
    } elseif ($type == 2) {
        $timestamp = $date_time;
        $date_time = date('Y-m-d H:i:s', $date_time);
    }
    if (!empty($format)) {
        return date($format, $timestamp);
    }
    $difference = time() - $timestamp;
    if ($difference <= 180) {
        return '刚刚';
    } elseif ($difference <= 3600) {
        return ceil($difference / 60) . '分钟前';
    } elseif ($difference <= 86400) {
        return ceil($difference / 3600) . '小时前';
    } elseif ($difference <= 2592000) {
        return ceil($difference / 86400) . '天前';
    } elseif ($difference <= 31536000) {
        return ceil($difference / 2592000) . '个月前';
    } else {
        return ceil($difference / 31536000) . '年前';
        // return $date_time;
    }
}

function get_device()
{
    $device = false;
    $user_agent = $_SERVER['HTTP_USER_AGENT']; // 获取用户代理字符串
    if (stristr($user_agent, 'iPad')) {
        $device = 'iPad';
    } elseif (stristr($user_agent, 'Android')) {
        $device = 'Android';
    } elseif (stristr($user_agent, 'Linux')) {
        $device = 'Linux';
    } elseif (stristr($user_agent, 'iPhone')) {
        $device = 'iPhone';
    } else {
        $device = 'PC';
    }
    return $device;
}

function get_broswer()
{
    $sys = $_SERVER['HTTP_USER_AGENT']; // 获取用户代理字符串
    if (stripos($sys, "Firefox/") > 0) {
        preg_match("/Firefox\/([^;)]+)+/i", $sys, $b);
        $exp[0] = "Firefox";
        $exp[1] = $b[1]; // 获取火狐浏览器的版本号
    } elseif (stripos($sys, "Maxthon") > 0) {
        preg_match("/Maxthon\/([\d\.]+)/", $sys, $aoyou);
        $exp[0] = "傲游";
        $exp[1] = $aoyou[1];
    } elseif (stripos($sys, "MSIE") > 0) {
        preg_match("/MSIE\s+([^;)]+)+/i", $sys, $ie);
        $exp[0] = "IE";
        $exp[1] = $ie[1]; // 获取IE的版本号
    } elseif (stripos($sys, "OPR") > 0) {
        preg_match("/OPR\/([\d\.]+)/", $sys, $opera);
        $exp[0] = "Opera";
        $exp[1] = $opera[1];
    } elseif (stripos($sys, "Edge") > 0) {
        // win10 Edge浏览器 添加了chrome内核标记 在判断Chrome之前匹配
        preg_match("/Edge\/([\d\.]+)/", $sys, $Edge);
        $exp[0] = "Edge";
        $exp[1] = $Edge[1];
    } elseif (stripos($sys, "Edg") > 0) {
        // 新Edge浏览器
        preg_match("/Edg\/([\d\.]+)/", $sys, $Edg);
        $exp[0] = "Edg";
        $exp[1] = $Edg[1];
    } elseif (stripos($sys, "Chrome") > 0) {
        preg_match("/Chrome\/([\d\.]+)/", $sys, $google);
        $exp[0] = "Chrome";
        $exp[1] = $google[1]; // 获取google chrome的版本号
    } elseif (stripos($sys, 'rv:') > 0 && stripos($sys, 'Gecko') > 0) {
        preg_match("/rv:([\d\.]+)/", $sys, $IE);
        $exp[0] = "IE";
        $exp[1] = $IE[1];
    } else {
        $exp[0] = "unknown";
        $exp[1] = "";
    }
    return $exp[0] . '(' . $exp[1] . ')';
}

/**
 * 获取客户端操作系统信息,包括win10
 *
 * @param
 *            null
 * @author https://blog.jjonline.cn/phptech/168.html
 * @return string
 */
function get_os()
{
    $agent = $_SERVER['HTTP_USER_AGENT'];
    $os = false;

    if (preg_match('/win/i', $agent) && strpos($agent, '95')) {
        $os = 'Windows 95';
    } elseif (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90')) {
        $os = 'Windows ME';
    } elseif (preg_match('/win/i', $agent) && preg_match('/98/i', $agent)) {
        $os = 'Windows 98';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent)) {
        $os = 'Windows Vista';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent)) {
        $os = 'Windows 7';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent)) {
        $os = 'Windows 8';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent)) {
        $os = 'Windows 10'; // 添加win10判断
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent)) {
        $os = 'Windows XP';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent)) {
        $os = 'Windows 2000';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent)) {
        $os = 'Windows NT';
    } elseif (preg_match('/win/i', $agent) && preg_match('/32/i', $agent)) {
        $os = 'Windows 32';
    } elseif (preg_match('/linux/i', $agent)) {
        $os = 'Linux';
    } elseif (preg_match('/unix/i', $agent)) {
        $os = 'Unix';
    } elseif (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'SunOS';
    } elseif (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'IBM OS/2';
    } elseif (preg_match('/Mac/i', $agent) && preg_match('/PC/i', $agent)) {
        $os = 'Macintosh';
    } elseif (preg_match('/PowerPC/i', $agent)) {
        $os = 'PowerPC';
    } elseif (preg_match('/AIX/i', $agent)) {
        $os = 'AIX';
    } elseif (preg_match('/HPUX/i', $agent)) {
        $os = 'HPUX';
    } elseif (preg_match('/NetBSD/i', $agent)) {
        $os = 'NetBSD';
    } elseif (preg_match('/BSD/i', $agent)) {
        $os = 'BSD';
    } elseif (preg_match('/OSF1/i', $agent)) {
        $os = 'OSF1';
    } elseif (preg_match('/IRIX/i', $agent)) {
        $os = 'IRIX';
    } elseif (preg_match('/FreeBSD/i', $agent)) {
        $os = 'FreeBSD';
    } elseif (preg_match('/teleport/i', $agent)) {
        $os = 'teleport';
    } elseif (preg_match('/flashget/i', $agent)) {
        $os = 'flashget';
    } elseif (preg_match('/webzip/i', $agent)) {
        $os = 'webzip';
    } elseif (preg_match('/offline/i', $agent)) {
        $os = 'offline';
    } else {

        $os = '未知操作系统';
    }
    return $os;
}

function get_ip()
{
    $ip = '';
    $ips = [];
    if (isset($_SERVER["HTTP_CLIENT_IP"])) {
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }

    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { // 获取代理ip
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    }
    if ($ip) {
        $ips = array_unshift($ips, $ip);
    }
    $count = count($ips);
    for ($i = 0; $i < $count; $i++) {
        if (!preg_match("/^(10|172.16|192.168)./i", $ips[$i])) { // 排除局域网ip
            $ip = $ips[$i];
            break;
        }
    }
    $tip = empty($_SERVER['REMOTE_ADDR']) ? $ip : $_SERVER['REMOTE_ADDR'];

    if ($tip == "127.0.0.1") { // 获得本地真实IP
        return get_onlineip();
    } else {
        return $tip;
    }
}

function get_onlineip()
{
    $mip = file_get_contents("http://city.ip138.com/city0.asp");
    if ($mip) {
        preg_match("/[.*]/", $mip, $sip);
        $p = array(
            "/[/",
            "/]/"
        );
        return preg_replace($p, "", $sip[0]);
    } else {
        return "获取本地IP失败！";
    }
}

// //根据ip获得访客所在地地名
function get_address($ip = '')
{
    if (empty($ip)) {
        $ip = get_ip();
    }

    $ipInfo = file_get_contents("https://apikey.net/?ip=" . $ip);
    $ipInfo = json_decode($ipInfo, true);

    if (isset($ipInfo['code']) && $ipInfo['code'] == 200) {
        return $ipInfo['address'];
    } else {
        return 'address 未知';
    }


}


function getResourcesTime()
{
    $data = [
        ['name' => ' 七天', 'day' => 7, 'index' => 'seven_day'],
        ['name' => ' 30天', 'day' => 30, 'index' => 'thirty_day'],
        ['name' => ' 60天', 'day' => 60, 'index' => 'sixty_day'],
        ['name' => ' 永久', 'day' => 0, 'index' => 'permanent'],
    ];
    return $data;
}


function rejectSubmit($log_no)
{
    $payconfig = sysconfig('pay');
    if (empty($payconfig)) {
        return json_encode([
            'code' => 0,
            'msg' => "请检查后台支付配置"
        ]);
        exit();
    }
    $payKey = root_path() . "/public/cert/apiclient_key.pem";
    $getData = new ApiV3Pay($payconfig['pay_appid'], $payconfig['pay_mchid'], $payKey, $payconfig['pay_serial_no']);
    $requestBody = $getData->rejectSubmit($log_no); // 获取请求主体的json数据

    if (!empty($requestBody['code'])) {
        echo json_encode([
            'code' => '0',
            'msg' => "微信商户" . $requestBody['message']
        ]);
        exit();
    }
    return json_encode([
        'code' => 1,
        'msg' => "操作成功",

    ]);
    exit();

}


function getTransfer($log_no)
{
    $payconfig = sysconfig('pay');
    if ($payconfig['pay_type'] == 2) { // 服务商

    } else {
        if ($payconfig['wx_transfer_version'] == 1) {

        } else {
            $payKey = root_path() . "/public/cert/apiclient_key.pem";
            $getData = new ApiV3Pay($payconfig['pay_appid'], $payconfig['pay_mchid'], $payKey, $payconfig['pay_serial_no']);
            $requestBody = $getData->transferSelelct($log_no); // 获取请求主体的json数据
            if (isset($requestBody['code'])) {
                return [
                    'code' => 0,
                    'msg' => "查询成功",
                    'data' => $requestBody
                ];
            }
            return [
                'code' => 1,
                'msg' => "查询成功",
                'data' => $requestBody
            ];
            exit();
        }
    }

}

/**
 * 获取签名token
 */
function accountToken($array)
{
    $key = config('app.agent_token_key');

    $token = array(
        'iat' => time(), // 签发时间
        'nbf' => time(), // 开始生效时间
        'exp' => time() + 60 * 60 * 24, // token过期时间
        'data' => $array
    ); // 存储的用户信息

    $jwt = JWT::encode($token, $key, "HS256", $key);
    return $jwt;
}

/**
 * 检查token是否过期
 * @param $token
 * @return \stdClass
 */
function checkAccountToken($token)
{
    $key = config('app.agent_token_key');
    $decoded = JWT::decode($token, new Key($key, 'HS256'));
    return $decoded;
}

function getliuguan($pid, $cid, $taskId = '')
{
    try {
        $getipHost = 'http://api.hailiangip.com:8422';
        $siteSet = sysconfig('site');
        $orderId = $siteSet['liuguang_ordersn'];            #用户编号
        $secret = $siteSet['liuguang_appsecret'];            #秘钥
        if (empty($siteSet['liuguang_ordersn']) || empty($siteSet['liuguang_appsecret'])) {
            return ['code' => 0, 'msg' => '请联系管理员设置流冠ip配置'];
        }
        $time = time();        #当前时间戳
        $type = 1;            #ip协议  1表示HTTP/HTTPS
        $num = 1;                #提取数量 1-200之间
        #城市	可为空
        $unbindTime = 300;        #占用时长（单位秒）
        $dataType = 0;        #返回的数据格式 0表示json
        $noDuplicate = 0;        #是否去重 0表示不去重 1表示24小时去重
        $singleIp = 0;        #异常切换  0表示切换  1表示不切换
        $sign = strtolower(md5('orderId=' . $orderId . '&secret=' . $secret . '&time=' . $time));
        $getipUrl = '/api/getIp?type=' . $type . '&num=' . $num . '&pid=' . $pid . '&unbindTime=' . $unbindTime . '&cid=' . $cid . '&orderId=' . $orderId . '&time=' . $time . '&sign=' . $sign . '&noDuplicate=' . $noDuplicate . '&dataType=' . $dataType . '&lineSeparator=0&singleIp=' . $singleIp;
        $getipLink = $getipHost . $getipUrl;
//	 echo $getipLink;exit;
        $redis = new \Redis();
        $password = isset(config('redis')["password"]) ? config('redis')["password"] : '';
        $port = empty(config('redis')["port"]) ? '6379' : config('redis')["port"];
        $redis->connect('127.0.0.1', $port);

        if (!empty($password)) {
            $redis->auth($password);
        }
        if ($taskId) {
            $ip = $redis->get("ip_" . $pid . '_' . $cid . $taskId);
        } else {
            $ip = $redis->get("ip_" . $pid . '_' . $cid);
        }

        if ($ip) {
            return ['code' => 1, 'data' => ['ip' => $ip]];
        }
        // 用get方式获取
        $ch = curl_init();
        $timeout = 5;
        curl_setopt($ch, CURLOPT_URL, $getipLink);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        $ret = curl_exec($ch);
        curl_close($ch);
        $retArr = json_decode($ret, true);
        
        if (isset($retArr['code']) && $retArr['code'] == 0) {
            if ($taskId) {
                $redis->set("ip_" . $pid . '_' . $cid . $taskId, $retArr['data'][0]['ip'] . ":" . $retArr['data'][0]['port'], 180);

            } else {
                $redis->set("ip_" . $pid . '_' . $cid, $retArr['data'][0]['ip'] . ":" . $retArr['data'][0]['port'], 180);

            }
            return ['code' => 1, 'data' => ['ip' => $retArr['data'][0]['ip'] . ":" . $retArr['data'][0]['port']]];
        } else {
            return ['code' => 0, 'msg' => '流冠ip配置获取失败，请联系管理员'];
        }




    } catch (Exception $exception) {
        return ['code' => 0, 'msg' => $exception->getMessage()];
    }
    function apiPost($url, $header, $data = NULL)
    {
        $request = Request();
        $headers = array(
            'Content-Type: application/json; charset=utf-8'
        );
        if (!empty($header)) {
            $headers = array_merge($headers, $header);
        }
        $userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';

        // 模拟提交数据函数
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_POST, true); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 600); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); // 类型为json
        $result = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Error POST' . curl_error($curl);
        }
        curl_close($curl); // 关键CURL会话
        return $result; // 返回数据
    }
}